import java.io.IOException;
import java.io.PrintStream;
import java.util.Random;
import java.util.TreeMap;
import java.util.Map;

public class RuleSet {

	//Map of cases to position in the genome.
	Map<Integer,Integer> rules = new TreeMap<Integer,Integer>();
	int[] genome;
	Random rn = new Random(Math.abs(System.nanoTime()));
	public RuleSet()
	{
		genome = new int[cases.length];
		
		for(int i=0;i<cases.length;i++)
		{
			rules.put(cases[i],i);
			genome[i] = rn.nextInt(2);
		}
	}
	
	public int ruleAnswer(Integer current)
	{
		return genome[rules.get(current)];
	}
	
	public void mutate(Float mutationRate)
	{
		Utils.mutate(genome, mutationRate);
	}
	
	public void crossover(RuleSet mate)
	{
		Utils.one_pt_crossover(this.genome, mate.genome);
	}
	
	public void loadBestRules()
	{
		for(int i=0; i<genome.length; i++)
		{
			genome[i] = bestRules[i];
		}
	}
	
	public void loadBestRules2()
	{
		for(int i=0; i<genome.length; i++)
		{
			genome[i] = bestRules2[i];
		}
	}
	
	public void loadBestRules3()
	{
		for(int i=0; i<genome.length; i++)
		{
			genome[i] = bestRules3[i];
		}
	}
	
	
	public void loadBestRules4()
	{
		for(int i=0; i<genome.length; i++)
		{
			genome[i] = bestRules4[i];
		}
	}
	
	public RuleSet copy()
	{
		RuleSet copy = new RuleSet();
		copy.rules.putAll(this.rules);
		System.arraycopy(this.genome, 0, copy.genome, 0, this.genome.length);
		return copy;
	}
	
	public void outputToFile(PrintStream writer)
	throws IOException
	{	
		StringBuffer buffer = new StringBuffer(128);
		buffer.append(" ");
		for(int i=0; i<genome.length; i++)
		{
			if(i!=0) buffer.append(",");
			buffer.append(genome[i]);
		}
		writer.append(buffer.toString());
	}
	
	public static final Integer bestRules4[] = {
			/**2500 for test pattern**/ 1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,1,1,1,1,0,1,1,0,1
	};
	
	public static final Integer bestRules3[] = {
	 /*2500 for checkeroard with changing initial condition**/ 1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,0,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0
	};
	
	public static final Integer bestRules2[] = {
		/** 2500 for checkerboard**/ 0,1,1,1,1,1,1,1,0,1,1,1,1,0,0,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,0
	};
	public static final Integer bestRules[] = {
		/** 2500 for checkerboard again**/ 0,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,0,0,0
		/** 2500 for checkerboard 0,1,1,1,1,1,1,1,0,1,1,1,1,0,0,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,0**/
		/**2226  0,0,0,0,0,1,1,0,0,0,1,1,1,1,0,1,0,0,1,1,1,0,0,1,0,1,0,1,1,0,1,1**/
		/**1310 0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,0,1,0,1,1,0,1,0,0,1,1,0**/
		/**1520  0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0,1,1,0,1,1,1,1,0,1,1,1,1,1,0**/
		/**1918  0,0,0,0,0,0,0,1,0,0,1,0,1,1,1,1,0,0,0,1,0,1,1,1,1,1,0,1,1,0,1,1**/
		/**1768  0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,1,0,1,0,0,1,1,1,0,0,1,1,1,1,0,1,1**/
	};
	
	public static final Integer cases[] = {00000,
		1,
		10,
		11,
		100,
		101,
		110,
		111,
		1000,
		1001,
		1010,
		1011,
		1100,
		1101,
		1110,
		1111,
		10000,
		10001,
		10010,
		10011,
		10100,
		10101,
		10110,
		10111,
		11000,
		11001,
		11010,
		11011,
		11100,
		11101,
		11110,
		11111};


}

